<!--export default class CallState {-->
<!--static STATUS_IDLE = 0;-->
<!--static STATUS_OUTGOING = 1;-->
<!--static STATUS_INCOMING = 2;-->
<!--static STATUS_CONNECTING = 3;-->
<!--static STATUS_CONNECTED = 4;-->
<!--}-->
<template>
  <div
    class="flex-column flex-align-center flex-justify-center voip-container"
    style="width: 100%; height: 100%"
    ref="rootContainer"
  >
    <div v-if="sharedMiscState.isElectron" ref="notClickThroughArea">
      <ElectronWindowsControlButtonView
        :title="'野火会议'"
        :macos="!sharedMiscState.isElectronWindowsOrLinux"
      />
      <ScreenShareControlView
        v-if="session && session.screenSharing"
        type="conference"
      />
      <h1 style="display: none">
        Voip-Conference 运行在新的window，和主窗口数据是隔离的！！
      </h1>
    </div>
    <div
      v-if="endReason !== undefined && endReason === 4"
      @click="rejoinConference"
      class="rejoin-container"
    >
      会议断开，点击重新加入
    </div>
    <div
      v-if="session"
      class="main-slider-container"
      v-bind:style="{
        display:
          session.screenSharing && sharedMiscState.isElectron ? 'none' : 'flex',
      }"
    >
      <div class="main">
        <header
          style="
            background: white;
            height: 20px;
            display: flex;
            justify-content: space-between;
          "
        >
          <a href="#" @click.prevent>
            <i
              class="icon-ion-information"
              style="padding: 0 10px"
              id="info-icon"
              v-bind:class="{ active: showConferenceSimpleInfoView }"
              @click.prevent="
                showConferenceSimpleInfoView = !showConferenceSimpleInfoView
              "
            />
          </a>
          <p style="flex: 1"></p>
          <p style="padding-right: 10px">{{ duration }}</p>
          <div>
            <a v-if="!audioOnly" href="#" @click.prevent>
              <i
                class="icon-ion-grid"
                style="padding: 0 10px"
                id="grid-icon"
                v-bind:class="{ active: showChooseLayoutView }"
                @click.prevent="showChooseLayoutView = !showChooseLayoutView"
                >宫格布局</i
              >
            </a>
            <!--                        TODO 条件显示，展示聊天界面，或者参与者列表界面时，才展示-->
            <a href="#" v-if="showSlider" @click.prevent>
              <i
                :class="
                  showSlider
                    ? 'icon-ion-arrow-left-b'
                    : 'icon-ion-arrow-right-b'
                "
                style="padding: 0 10px"
                @click="toggleSliderView"
              ></i>
            </a>
          </div>
        </header>
        <div
          v-if="showConferenceSimpleInfoView"
          v-v-on-click-outside="hideConferenceSimpleInfoView"
          style="position: absolute; left: 10px; top: 50px; z-index: 1000"
        >
          <ConferenceSimpleInfoView :session="session" />
        </div>
        <div
          v-if="showChooseLayoutView"
          v-v-on-click-outside="hideChooseLayoutView"
          style="position: absolute; right: 10px; top: 50px; z-index: 1000"
        >
          <ChooseConferenceLayoutView
            :current-layout="computedCurrentLayout"
            :session="session"
          />
        </div>
        <div
          style="
            position: absolute;
            left: 10px;
            bottom: 80px;
            width: 300px;
            max-height: 300px;
            overflow: hidden;
            background: transparent;
            z-index: 1000;
          "
        >
          <ConferenceConversationFloatingView :session="session" />
        </div>
        <div class="conference-main-content-container">
          <!--main-->
          <!--video-->
          <div v-if="!audioOnly" style="width: 100%; height: 100%">
            <i
              v-if="computedCurrentLayout === 0 && currentGridPageIndex > 0"
              style="
                position: absolute;
                top: 50%;
                left: 0;
                color: #c8cacc;
                z-index: 1000;
                font-size: 40px;
                padding: 0 10px;
              "
              class="icon-ion-arrow-left-c"
              @click="prePage"
            ></i>
            <i
              v-if="
                computedCurrentLayout === 0 &&
                currentGridPageIndex < gridPageCount - 1
              "
              style="
                position: absolute;
                top: 50%;
                right: 0;
                color: #c8cacc;
                z-index: 1000;
                font-size: 40px;
                padding: 0 10px;
              "
              class="icon-ion-arrow-right-c"
              @click="nextPage"
            ></i>
            <!--                    宫格布局-->
            <section
              v-if="computedCurrentLayout === 0"
              class="content-container grid video"
            >
              <!--participants include self-->
              <ConferenceParticipantVideoView
                v-for="participant in currentPageParticipants"
                :key="participant.uid + '-' + participant._isScreenSharing"
                :participant="participant"
                :session="session"
              >
              </ConferenceParticipantVideoView>
            </section>

            <!--                    演讲者布局-->
            <section v-else class="content-container focus video">
              <div
                :style="{
                  width: hideFocusLayoutParticipantListVideoView
                    ? '100%'
                    : 'calc(100% - 200px)',
                  height: '100%',
                  position: 'relative',
                }"
              >
                <video
                  v-if="
                    computedFocusVideoParticipant &&
                    !computedFocusVideoParticipant._isAudience &&
                    (!computedFocusVideoParticipant._isVideoMuted ||
                      computedFocusVideoParticipant._isScreenSharing) &&
                    computedFocusVideoParticipant._stream
                  "
                  v-bind:style="{
                    objectFit: computedFocusVideoParticipant._isScreenSharing
                      ? 'contain'
                      : 'fit',
                  }"
                  style="width: 100%; height: 100%"
                  :srcObject.prop="
                    computedFocusVideoParticipant._screenShareStream
                      ? computedFocusVideoParticipant._screenShareStream
                      : computedFocusVideoParticipant._stream
                  "
                  :muted="
                    computedFocusVideoParticipant.uid === selfUserInfo.uid
                  "
                  playsInline
                  autoPlay
                />
                <div
                  @click="toggleParticipantListVideoView"
                  style="
                    position: absolute;
                    top: 50%;
                    right: 0;
                    color: #c8cacc;
                    z-index: 1000;
                    font-size: 40px;
                  "
                >
                  <i
                    :class="
                      hideFocusLayoutParticipantListVideoView
                        ? 'icon-ion-arrow-left-b'
                        : 'icon-ion-arrow-right-b'
                    "
                  ></i>
                </div>
              </div>
              <div
                v-show="!hideFocusLayoutParticipantListVideoView"
                class="focus-mode-participant-list-container"
              >
                <!--participants include self-->
                <ConferenceParticipantVideoView
                  v-for="participant in participantUserInfos"
                  :key="participant.uid + '-' + participant._isScreenSharing"
                  :participant="participant"
                  :session="session"
                >
                </ConferenceParticipantVideoView>
              </div>
            </section>
          </div>
          <!--audio-->
          <div v-else style="width: 100%; height: 100%">
            <div
              style="
                background: white;
                height: 50px;
                display: flex;
                justify-content: center;
                align-items: center;
              "
            >
              <div
                style="
                  background: #daeafe;
                  width: 300px;
                  height: 40px;
                  padding: 0 5px;
                  border-radius: 3px;
                  display: flex;
                  flex-direction: column;
                  justify-content: center;
                "
              >
                <p class="single-line">{{ '正在讲话: ' + speakingUserName }}</p>
              </div>
            </div>
            <section class="content-container audio">
              <!--participants-->
              <div
                v-for="participant in participantUserInfos"
                :key="participant.uid"
                class="participant-audio-item"
              >
                <video
                  v-if="
                    audioOnly &&
                    participant._stream &&
                    !participant._isVideoMuted
                  "
                  class="hidden-video"
                  :srcObject.prop="participant._stream"
                  :muted="participant.uid === selfUserInfo.uid"
                  playsInline
                  autoPlay
                />
                <!-- video 标签不能播放没有视频的流 -->
                <audio
                  v-else-if="
                    audioOnly &&
                    participant._stream &&
                    participant._isVideoMuted
                  "
                  class="hidden-video"
                  :srcObject.prop="participant._stream"
                  :ref="participant.uid + '-audio'"
                  :muted="participant.uid === selfUserInfo.uid"
                  playsInline
                  autoPlay
                />
                <div style="position: relative">
                  <img
                    class="avatar"
                    v-bind:class="{ highlight: participant._volume > 0 }"
                    :src="participant.portrait"
                    :alt="participant"
                  />
                  <i
                    v-if="participant._isHost"
                    class="indicator icon-ion-person"
                    style="background: #fd802e"
                  ></i>
                  <i
                    v-if="participant._isAudience"
                    class="indicator icon-ion-ios-mic-off"
                    style="color: red"
                  ></i>
                </div>
                <p class="single-line">{{ userName(participant) }}</p>
              </div>
            </section>
          </div>
          <!--actions-->
          <footer>
            <div class="duration-action-container">
              <p v-if="false">{{ duration }}</p>
              <div class="action-container">
                <div class="action">
                  <img
                    v-if="!session.audience && !session.audioMuted"
                    @click="muteAudio"
                    class="action-img"
                    src="@/assets/images/av_conference_audio.png"
                  />
                  <img
                    v-else
                    @click="muteAudio"
                    class="action-img"
                    src="@/assets/images/av_conference_audio_mute.png"
                  />
                  <p>静音</p>
                </div>
                <div class="action" v-if="!session.screenSharing">
                  <img
                    v-if="!session.audience && !session.videoMuted"
                    @click="muteVideo"
                    class="action-img"
                    src="@/assets/images/av_conference_video.png"
                  />
                  <img
                    v-else
                    @click="muteVideo"
                    class="action-img"
                    src="@/assets/images/av_conference_video_mute.png"
                  />
                  <p>视频</p>
                </div>
                <div class="action">
                  <img
                    v-if="!session.screenSharing"
                    @click="screenShare"
                    class="action-img"
                    src="@/assets/images/av_conference_screen_sharing.png"
                  />
                  <img
                    v-else
                    @click="screenShare"
                    class="action-img"
                    src="@/assets/images/av_conference_screen_sharing_hover.png"
                  />
                  <p class="single-line">共享屏幕</p>
                </div>
                <div class="action" @click="chat">
                  <i
                    class="icon-ion-ios-chatboxes"
                    style="
                      width: 40px;
                      height: 40px;
                      font-size: 40px;
                      color: black;
                    "
                    v-bind:style="{
                      color: showConversationView ? 'white' : 'black',
                    }"
                  />
                  <p>聊天</p>
                </div>
                <div
                  v-if="
                    conferenceManager.conferenceInfo &&
                    selfUserInfo.uid !== conferenceManager.conferenceInfo.owner
                  "
                  class="action"
                >
                  <img
                    v-if="!conferenceManager.isHandUp"
                    @click="handup"
                    class="action-img"
                    src="@/assets/images/av_conference_handup.png"
                  />
                  <img
                    v-else
                    @click="handup"
                    class="action-img"
                    src="@/assets/images/av_conference_handup_hover.png"
                  />
                  <p class="single-line">举手</p>
                </div>
                <div class="action">
                  <img
                    @click.stop="members"
                    class="action-img"
                    v-bind:style="{
                      filter: showConferenceManageView
                        ? 'invert(100%)'
                        : 'none',
                    }"
                    src="@/assets/images/av_conference_members.png"
                  />
                  <p>管理</p>
                </div>
                <div class="action">
                  <img
                    @click="hangup"
                    class="action-img"
                    src="@/assets/images/av_conference_end_call.png"
                  />
                  <p>结束</p>
                </div>
              </div>
            </div>
          </footer>
        </div>
      </div>
      <div class="slider">
        <div class="title" style="display: none">TODO</div>
        <ConferenceManageView
          v-if="showConferenceManageView"
          v-bind:class="{ active: showConferenceManageView }"
          :participants="participantUserInfos"
          :session="session"
        />
        <ConversationView
          v-if="showConversationView && sharedMiscState.isElectron"
          class="conversation-view"
          style="height: 100%"
          :title="conferenceManager.conferenceInfo.conferenceTitle"
          :input-options="{
            disableScreenShot: true,
            disableHistory: true,
            disableVoip: true,
            disableChannelMenu: true,
          }"
        />
      </div>
    </div>
  </div>
</template>

<script>
import avenginekit from '../../../wfc/av/internal/engine.min'
import CallSessionCallback from '../../../wfc/av/engine/callSessionCallback'
import CallState from '../../../wfc/av/engine/callState'
import localStorageEmitter from '../../../ipc/localStorageEmitter'
import { currentWindow, isElectron } from '../../../platform'
import ScreenOrWindowPicker from '../ScreenOrWindowPicker'
import CallEndReason from '../../../wfc/av/engine/callEndReason'
import ScreenShareControlView from '../ScreenShareControlView'
import avenginekitproxy from '../../../wfc/av/engine/avenginekitproxy'
import ElectronWindowsControlButtonView from '../../common/ElectronWindowsControlButtonView'
import store from '../../../store'
import VideoType from '../../../wfc/av/engine/videoType'
import IpcEventType from '../../../ipcEventType'
import ConferenceParticipantVideoView from './ConferenceParticipantVideoView'
import ConversationView from '../../main/conversation/ConversationView'
import ConferenceSimpleInfoView from './ConferenceSimpleInfoView'
import ChooseConferenceLayoutView from './ChooseConferenceLayoutView'
import ConferenceConversationFloatingView from './ConferenceConversationFloatingView'
import conferenceManager from './conferenceManager'
import ConferenceManageView from './ConferenceManageView'
import wfc from '../../../wfc/client/wfc'
import LocalStorageIpcEventType from '../../../ipc/localStorageIpcEventType'
import UserInfo from '../../../wfc/model/userInfo'
import ConversationType from '../../../wfc/model/conversationType'
import Conversation from '../../../wfc/model/conversation'
import ConversationInfo from '../../../wfc/model/conversationInfo'
import ChannelInfo from '../../../wfc/model/channelInfo'
import ChatRoomInfo from '../../../wfc/model/chatRoomInfo'
import { vOnClickOutside } from '@vueuse/components'
import { markRaw } from 'vue'
import EventType from '../../../wfc/client/wfcEvent'

export default {
  name: 'Conference',
  data() {
    return {
      session: null,
      audioOnly: false,
      status: 1,
      selfUserInfo: null,
      participantUserInfos: [],

      startTimestamp: 0,
      currentTimestamp: 0,

      showSlider: false,
      showConferenceManageView: false,
      showConversationView: false,
      sharedMiscState: store.state.misc,
      videoInputDeviceIndex: 0,

      refreshUserInfoInternal: 0,

      endReason: undefined,

      conferenceManager: conferenceManager,

      // -1，默认布局，也就是宫格布局；0, 宫格视图；1，演讲者视图
      currentLayout: -1,

      // 宫格视图
      currentGridPageIndex: 0,
      participantCountPerGridPage: 9,

      // 演讲者视图
      speakingVideoParticipant: null,
      hideFocusLayoutParticipantListVideoView: false,

      showConferenceSimpleInfoView: false,
      showChooseLayoutView: false,
    }
  },
  components: {
    ConferenceManageView,
    ConferenceConversationFloatingView,
    ChooseConferenceLayoutView,
    ConferenceSimpleInfoView,
    ConferenceParticipantVideoView,
    ScreenShareControlView,
    ElectronWindowsControlButtonView,
    ConversationView,
  },
  methods: {
    // 用来解决 iOS 上，不能自动播放问题
    autoPlay() {
      if (isElectron()) {
        return
      }
      console.log('auto play')
      if (!this.autoPlayInterval) {
        this.autoPlayInterval = setInterval(() => {
          try {
            let videos = document.getElementsByTagName('video')
            let allPlaying = true
            for (const video of videos) {
              if (video.paused) {
                allPlaying = false
                break
              }
            }
            // participantUserInfos 不包含自己
            if (
              allPlaying &&
              videos.length ===
                this.participantUserInfos.filter((p) => !p._isAudience).length +
                  1
            ) {
              clearInterval(this.autoPlayInterval)
              this.autoPlayInterval = 0
              console.log('auto play, allPlaying', videos.length)
              return
            }

            for (const video of videos) {
              if (video.paused) {
                let p = video.play()
                if (p !== undefined) {
                  p.catch((err) => {
                    // do nothing
                  })
                }
              }
            }
          } catch (e) {
            // do nothing
          }
        }, 100)
      }
    },
    setupSessionCallback() {
      let sessionCallback = new CallSessionCallback()

      sessionCallback.didChangeState = (state) => {
        console.log('didChangeState', state)
        this.status = state
        if (state === CallState.STATUS_CONNECTED) {
          // 比如没有摄像头，但发起视频通话时，会自动 muteVideo
          this.selfUserInfo._isVideoMuted = this.session.videoMuted
          if (this.startTimestamp === 0) {
            this.startTimestamp = new Date().getTime()
            this.timer = setInterval(() => {
              this.currentTimestamp = new Date().getTime()
            }, 1000)
          }
        } else if (state === CallState.STATUS_IDLE) {
          if (this.timer) {
            clearInterval(this.timer)
          }
        }
      }

      sessionCallback.onInitial = (
        session,
        selfUserInfo,
        initiatorUserInfo
      ) => {
        //this.session.rotateAng = 90;

        selfUserInfo._isHost = session.host === selfUserInfo.uid
        selfUserInfo._isAudience = session.audience
        selfUserInfo._isVideoMuted = session.videoMuted
        selfUserInfo._isAudioMuted = session.audioMuted
        selfUserInfo._volume = 0
        // 先添加属性，在赋值，才能 reactive
        this.selfUserInfo = selfUserInfo
        this.participantUserInfos = [selfUserInfo]

        console.log('oninitial', selfUserInfo._isAudience)
        // pls refer to: https://vuejs.org/v2/guide/reactivity.html
        this.$set(this.selfUserInfo, '_stream', null)
        this.$set(this.selfUserInfo, '_screenShareStream', null)
        this.$set(this.selfUserInfo, '_isScreenSharing', false)
        this.participantUserInfos.forEach((p) => this.$set(p, '_stream', null))

        this.session = session
        if (isElectron()) {
          document.title = session.title
        }

        conferenceManager.getConferenceInfo(session.callId)
      }

      sessionCallback.didCreateLocalVideoTrack = (stream, screenShare) => {
        console.log('didCreateLocalVideoTrack', screenShare)
        this.selfUserInfo._stream = stream
        this.selfUserInfo._screenShareStream = null
        this.selfUserInfo._isVideoMuted = false
        this.selfUserInfo._isScreenSharing = screenShare
        this.autoPlay()
      }

      sessionCallback.didRotateLocalVideoTrack = (stream) => {
        console.log('didRotateLocalVideoTrack', stream.getAudioTracks())
        this.selfUserInfo._stream = stream
        this.selfUserInfo._stream.timestamp = new Date().getTime()
      }

      sessionCallback.didScreenShareEnded = () => {
        console.log(
          'didScreenShareEnded',
          this.session.videoMuted,
          this.session.audioMuted
        )
        if (isElectron()) {
          currentWindow.setIgnoreMouseEvents(false)
        }
        this.selfUserInfo._isScreenSharing = false
        this.selfUserInfo._isVideoMuted = this.session.videoMuted
      }

      sessionCallback.didCreateLocalVideoTrackError = () => {
        // TODO
        // 没有摄像头或者麦克风，加入会议时，会回调到此处，自己断会显示自己的头像，其他端会显示黑屏
        // 可以进行相关提示
      }

      sessionCallback.didReceiveRemoteVideoTrack = (
        userId,
        stream,
        screenSharing
      ) => {
        let p
        console.log('didReceiveRemoteVideoTrack', userId, stream, screenSharing)
        let index = -1
        for (let i = 0; i < this.participantUserInfos.length; i++) {
          p = this.participantUserInfos[i]
          if (p.uid === userId && p._isScreenSharing === screenSharing) {
            index = i
            p._stream = stream
            p._stream.timestamp = new Date().getTime()
            break
          }
        }
        // if (index > -1) {
        //     this.$set(this.participantUserInfos, index, p);
        // }
        this.autoPlay()
      }

      sessionCallback.didRemoveRemoteVideoTrack = (userId) => {
        console.log('didRemoveRemoteVideoTrack', userId)
      }

      sessionCallback.didParticipantJoined = (userId, screenSharing) => {
        console.log('didParticipantJoined', userId, screenSharing)
        let userInfo = wfc.getUserInfo(userId)
        let subscriber = this.session.getSubscriber(userId, screenSharing)
        userInfo._stream = subscriber.stream
        userInfo._isAudience = subscriber.audience
        userInfo._isHost = this.session.host === userId
        userInfo._isVideoMuted = subscriber.videoMuted
        userInfo._isAudioMuted = subscriber.audioMuted
        userInfo._volume = 0
        userInfo._isScreenSharing = screenSharing
        // 动态添加的属性不是 reactive 的，故直接创建个新的对象
        // 其实这个问题很奇怪，只有发起会议，第一次进入该会议的时候，其他端加入，参与者列表会不刷新；重新进入等，都一切正常
        this.participantUserInfos.push(Object.assign(new UserInfo(), userInfo))
        console.log(
          'joined',
          userInfo,
          subscriber.audience,
          this.participantUserInfos.length
        )
      }

      sessionCallback.didParticipantLeft = (
        userId,
        endReason,
        screenSharing
      ) => {
        console.log(
          'didParticipantLeft',
          userId,
          endReason,
          screenSharing,
          JSON.stringify(this.participantUserInfos),
          this.participantUserInfos.length
        )
        //this.participantUserInfos = this.participantUserInfos.filter(p => p.uid !== userId && p._isScreenSharing !== screenSharing);
        this.participantUserInfos = this.participantUserInfos.filter((p) => {
          return !(p.uid === userId && p._isScreenSharing === screenSharing)
        })
        //fixme 上面可能会没有触发重新计算 focusVideoParticipant
        console.log(
          'didParticipantLeft d',
          userId,
          endReason,
          screenSharing,
          this.participantUserInfos.length
        )
      }

      sessionCallback.didCallEndWithReason = (reason) => {
        console.log('callEndWithReason', reason)
        conferenceManager.addHistory(
          conferenceManager.conferenceInfo,
          new Date().getTime() -
            conferenceManager.conferenceInfo.startTime * 1000
        )

        // 可以根据reason，进行一些提示
        // alert('会议已结束');

        this.endReason = reason
        if (reason === CallEndReason.REASON_MediaError) {
          return
        }
        if (reason === CallEndReason.RoomNotExist) {
          console.log('join conference failed', reason, this.session)
          let obj = { reason: reason, session: this.session }
          localStorageEmitter.send(
            LocalStorageIpcEventType.joinConferenceFailed,
            obj
          )
        }
        this.session.closeVoipWindow()
        this.session = null
      }

      sessionCallback.onRequestChangeMode = (audience) => {
        console.log('onRequestChangeMode', audience)
        if (audience) {
          this.session.switchAudience(true)
          return
        }
        this.$alert({
          content: '主持人邀请你参与互动',
          cancelCallback: () => {
            // do nothing
          },
          confirmCallback: () => {
            this.session.switchAudience(false)
          },
        })
      }

      sessionCallback.didChangeType = (userId, audience, screenSharing) => {
        console.log('didChangeType', userId, audience, screenSharing)
        this.participantUserInfos.forEach((u) => {
          if (u.uid === userId && u._isScreenSharing === screenSharing) {
            u._isAudience = audience
            if (audience) {
              u._stream = null
            }
            if (
              this.speakingVideoParticipant &&
              this.speakingVideoParticipant.uid === u.uid
            ) {
              this.speakingVideoParticipant = null
            }
          }
        })
      }

      sessionCallback.didReportAudioVolume = (userId, volume) => {
        let userInfo
        if (userId === this.selfUserInfo.uid) {
          this.selfUserInfo._volume = volume
          userInfo = this.selfUserInfo
        } else {
          this.participantUserInfos.forEach((u) => {
            if (u.uid === userId && u._isScreenSharing === false) {
              u._volume = volume
              userInfo = u
            }
          })
        }
        if (this.currentLayout === 0) {
          return
        }

        if (!userInfo) {
          return
        }

        if (userInfo._isVideoMuted) {
          return
        }

        if (this.conferenceFocusUser) {
          return this.conferenceFocusUser
        }

        if (!this.speakingVideoParticipant) {
          this.speakingVideoParticipant = userInfo
        } else if (userInfo._volume > this.speakingVideoParticipant._volume) {
          this.speakingVideoParticipant = userInfo
        }
      }

      sessionCallback.didMuteStateChanged = (participants) => {
        console.log('conference', 'didMuteStateChanged', participants)
        participants.forEach((p) => {
          // 自己
          if (p === this.selfUserInfo.uid) {
            console.log(
              'conference',
              'didMuteStateChanged self',
              this.session.videoMuted
            )
            this.selfUserInfo._isVideoMuted = this.session.videoMuted
            return
          }
          let s = this.session.getSubscriber(p)
          if (!s) {
            return
          }
          console.log(
            'conference',
            'didMuteStateChanged',
            p,
            s.videoMuted,
            s.audioMuted
          )
          this.participantUserInfos.forEach((u) => {
            if (u.uid === p && u._isScreenSharing === false) {
              let subscriber = this.session.getSubscriber(p)
              u._isVideoMuted = subscriber.videoMuted
              u._isAudioMuted = subscriber.audioMuted
              if (
                this.speakingVideoParticipant &&
                this.speakingVideoParticipant.uid === u.uid
              ) {
                this.speakingVideoParticipant = null
              }
            }
          })
        })
      }

      sessionCallback.didMediaLostPacket = (
        media,
        lostPacket,
        screenSharing
      ) => {
        console.log('didMediaLostPacket', media, lostPacket, screenSharing)
        if (lostPacket > 6) {
          console.log('您的网络不好')
        }
      }

      sessionCallback.didUserMediaLostPacket = (
        userId,
        media,
        lostPacket,
        uplink,
        screenSharing
      ) => {
        console.log(
          'didUserMediaLostPacket',
          userId,
          media,
          lostPacket,
          uplink,
          screenSharing
        )
        //如果uplink ture对方网络不好，false您的网络不好
        //接收方丢包超过10为网络不好
        if (lostPacket > 10) {
          if (uplink) {
            let userInfos = this.participantUserInfos.filter(
              (u) => u.uid === userId && u._isScreenSharing === screenSharing
            )
            if (userInfos && userInfos.length > 0) {
              console.log(userInfos[0].displayName, '网络不好')
            }
          } else {
            console.log('您的网络不好')
          }
        }
      }

      if (isElectron()) {
        avenginekit.setup(sessionCallback)
      } else {
        avenginekit.sessionCallback = sessionCallback
      }
    },

    hangup() {
      this.session.leaveConference(false)
      conferenceManager.addHistory(
        conferenceManager.conferenceInfo,
        new Date().getTime() - conferenceManager.conferenceInfo.startTime * 1000
      )
    },

    muteAudio() {
      let enable = this.session.audioMuted ? true : false
      if (
        enable &&
        this.session.audience &&
        !conferenceManager.isOwner() &&
        !conferenceManager.conferenceInfo.allowSwitchMode
      ) {
        this.requestUnmute(true)
        return
      }
      this.enableAudio(enable)
    },

    async enableAudio(enable) {
      let result = await this.session.setAudioEnabled(enable)
      if (!result) {
        return
      }
      this.selfUserInfo._isAudioMuted = !enable

      console.log(
        'muteAudio',
        this.selfUserInfo._isAudioMuted,
        this.session.audience
      )
      if (enable) {
        if (this.session.audience) {
          await this.session.switchAudience(false)
          this.selfUserInfo._isAudience = false
        }
      } else {
        if (
          this.session.videoMuted &&
          !this.selfUserInfo._isScreenSharing &&
          !this.session.audience
        ) {
          await this.session.switchAudience(true)
          this.selfUserInfo._isAudience = true
        }
      }
    },
    muteVideo() {
      let enable = this.session.videoMuted ? true : false
      if (
        enable &&
        this.session.audience &&
        !conferenceManager.isOwner() &&
        !conferenceManager.conferenceInfo.allowSwitchMode
      ) {
        this.requestUnmute(false)
        return
      }
      this.enableVideo(enable)
    },

    async enableVideo(enable) {
      let result = await this.session.setVideoEnabled(enable)
      if (!result) {
        return
      }
      this.selfUserInfo._isVideoMuted = !enable

      console.log(
        'muteVideo result',
        this.selfUserInfo._isVideoMuted,
        this.session.audience
      )
      if (enable) {
        if (this.session.audience) {
          await this.session.switchAudience(false)
          this.selfUserInfo._isAudience = false
        }
      } else {
        if (this.session.audioMuted && !this.session.audience) {
          await this.session.switchAudience(true)
          this.selfUserInfo._isAudience = true
        }
      }
    },

    requestUnmute(audio) {
      if (audio && conferenceManager.allowUnmuteAudio) {
        this.enableAudio(true)
        return
      }

      if (!audio && conferenceManager.allowUnmuteVideo) {
        this.enableVideo(true)
        return
      }
      this.$alert({
        content: audio
          ? '主持人不允许解除静音，您可以向主持人申请解除静音'
          : '主持人不允许打开摄像头，您可以向主持人申请打开摄像头',
        confirmText: '申请',
        cancelCallback: () => {
          // do nothing
        },
        confirmCallback: () => {
          conferenceManager.applyUnmute(audio, false)
        },
      })
    },

    down2voice() {
      this.session.downgrade2Voice()
    },

    members() {
      this.showConferenceManageView = !this.showConferenceManageView
      this.toggleSliderView()
    },

    chat() {
      if (isElectron()) {
        this.showConversationView = !this.showConversationView
        this.toggleSliderView()
      } else {
        let conversation = new Conversation(
          ConversationType.ChatRoom,
          this.session.callId,
          0
        )
        let chatroomInfo = new ChatRoomInfo()
        chatroomInfo.chatRoomId = this.session.callId
        chatroomInfo.title = this.session.title
        conversation._target = chatroomInfo
        conversation._target._displayName = chatroomInfo.title
        let conversationInfo = new ConversationInfo()
        conversationInfo.conversation = conversation
        store.setCurrentConversationInfo(conversationInfo)
        this.$router.replace('/home')
      }
    },

    hideParticipantList() {
      this.showConferenceManageView && (this.showConferenceManageView = false)
      this.toggleSliderView()
    },

    toggleSliderView() {
      if (!this.showSlider) {
        if (isElectron()) {
          let size = currentWindow.getSize()
          currentWindow.setSize(size[0] + 350, size[1], false)
        } else {
          window.resizeTo(window.innerWidth + 360, window.outerHeight)
        }
        this.$refs.rootContainer.style.setProperty('--slider-width', '350px')
      } else {
        if (isElectron()) {
          let size = currentWindow.getSize()
          this.$refs.rootContainer.style.setProperty('--slider-width', '0px')
          currentWindow.setSize(size[0] - 350, size[1], false)
        } else {
          this.$refs.rootContainer.style.setProperty('--slider-width', '0px')
          window.resizeTo(window.innerWidth - 350, window.outerHeight)
        }

        this.showConferenceManageView = false
        this.showConversationView = false
      }
      this.showSlider = !this.showSlider
    },

    async screenShare() {
      // if (true) {
      //     navigator.mediaDevices.enumerateDevices().then(deviceInfos => {
      //         // test input
      //         for (const deviceInfo of deviceInfos) {
      //             if (this.testCount % 2 === 0) {
      //                    //仅仅是为测试了，生成不能这么写死
      //                 if (deviceInfo.label === "外置麦克风 (Built-in)") {
      //                     console.log('audioInput 外置');
      //                     this.session.setAudioInputDeviceId(deviceInfo.deviceId);
      //                     break;
      //                 }
      //             } else {
      //                 if (deviceInfo.label === "MacBook Pro麦克风 (Built-in)") {
      //                     console.log('audioInput 内置');
      //                     this.session.setAudioInputDeviceId(deviceInfo.deviceId);
      //                     break;
      //                 }
      //             }
      //         }
      //
      //         // test output
      //         // for (const deviceInfo of deviceInfos) {
      //         //     if (this.testCount % 2 === 0) {
      //         //         if (deviceInfo.label === "外置耳机 (Built-in)") {
      //         //             console.log('audioOut 外置');
      //         //             this.setAudioOutputDeviceId(deviceInfo.deviceId)
      //         //             break;
      //         //         }
      //         //     } else {
      //         //         if (deviceInfo.label === "MacBook Pro扬声器 (Built-in)") {
      //         //             console.log('audioOutput 内置');
      //         //             this.setAudioOutputDeviceId(deviceInfo.deviceId)
      //         //             break;
      //         //         }
      //         //     }
      //         // }
      //
      //     }).catch(err => {
      //         console.log()
      //     })
      //     this.testCount++;
      //     return;
      // }

      if (this.session.screenSharing) {
        this.session.stopScreenShare()
        console.log(
          'stopScreenShare',
          this.session.videoMuted,
          this.session.audioMuted
        )
        if (this.session.videoMuted && this.session.audioMuted) {
          this.session.switchAudience(true)
        }
        // currentWindow.setIgnoreMouseEvents(false)
      } else {
        if (isElectron()) {
          let beforeClose = (event) => {
            // What a gamble... 50% chance to cancel closing
            if (!event.params) {
              return
            }
            if (event.params.source) {
              let source = event.params.source
              let desktopShareOptions = {
                sourceId: source.id,
                // minWidth: 1280,
                maxWidth: 1280,
                // minHeight: 720,
                maxHeight: 720,
              }

              if (this.session.audience) {
                this.session
                  .switchAudience(false)
                  .then(() => {
                    this.session.startScreenShare(desktopShareOptions)
                  })
                  .catch((err) => {
                    console.error(err)
                  })
              } else {
                this.session.startScreenShare(desktopShareOptions)
              }
              avenginekitproxy.emitToMain(IpcEventType.START_SCREEN_SHARE, {})
            }
          }
          this.$modal.show(
            markRaw(ScreenOrWindowPicker),
            {},
            null,
            {
              width: 800,
              height: 600,
              name: 'screen-window-picker-modal',
              clickToClose: false,
            },
            {
              // 'before-open': beforeOpen,
              'before-close': beforeClose,
              // 'closed': closed,
            }
          )
        } else {
          if (this.session.audience) {
            await this.session.switchAudience(false)
          }
          this.session.startScreenShare({
            frameRate: 30,
          })
        }
      }
    },

    // 设置音频输出设备
    setAudioOutputDeviceId(deviceId) {
      let audioEls = this.$el.getElementsByTagName('audio')
      for (const audioEl of audioEls) {
        audioEl.setSinkId(deviceId)
      }
      let videoEls = this.$el.getElementsByTagName('video')
      for (const videoEl of videoEls) {
        videoEl.setSinkId(deviceId)
      }
    },

    handup() {
      conferenceManager.handUp(!conferenceManager.isHandUp)
    },

    userName(user) {
      let name = ''
      if (user.groupAlias) {
        name = user.groupAlias
      } else if (user.friendAlias) {
        name = user.friendAlias
      } else if (user.displayName) {
        name = user.displayName
      } else {
        name = user.name
      }
      return name
    },

    timestampFormat(timestamp) {
      timestamp = ~~(timestamp / 1000)
      let str = ''
      let hour = ~~(timestamp / 3600)
      str = hour > 0 ? (hour < 10 ? '0' : '') + hour + ':' : ''
      let min = ~~((timestamp % 3600) / 60)
      str += (min < 10 ? '0' : '') + min + ':'
      let sec = ~~(timestamp % 60)
      str += (sec < 10 ? '0' : '') + sec
      return str
    },

    // TODO 删除，可以直接监听用户信息变化了
    refreshUserInfos() {
      let toRefreshUsers = []
      this.participantUserInfos.forEach((pu) => {
        if (!pu.updateDt) {
          toRefreshUsers.push(pu.uid)
        }
      })

      if (toRefreshUsers.length > 0) {
        console.log('to refreshUsers', toRefreshUsers)
        let userInfos = wfc.getUserInfos(toRefreshUsers, '')
        userInfos.forEach((u) => {
          let index = this.participantUserInfos.findIndex(
            (p) => p.uid === u.uid
          )
          if (u.updateDt && index > -1) {
            let ou = this.participantUserInfos[index]
            u._stream = ou._stream
            u._isAudience = ou._isAudience
            u._isHost = ou._isHost
            u._isVideoMuted = ou._isVideoMuted
            u._isAudioMuted = ou._isAudioMuted
            u._volume = ou._volume
            // FYI: https://v2.vuejs.org/v2/guide/reactivity#Change-Detection-Caveats
            this.participantUserInfos.splice(index, 1, u)
          }
        })
      }
    },

    rejoinConference() {
      avenginekit.joinConference({
        callId: this.session.callId,
        pin: this.session.pin,
        host: this.session.host,
        tile: this.session.title,
        desc: this.session.desc,
        audioOnly: this.session.audioOnly,
        audience: this.session.audience,
        advance: this.session.advance,
        muteVideo: this.session.videoMuted,
        muteAudio: this.session.audioMuted,
        extra: this.session.extra,
        callExtra: this.session.callExtra,
        selfUserInfo: this.selfUserInfo,
      })
      this.endReason = undefined
    },

    prePage() {
      this.currentGridPageIndex--
      if (this.currentGridPageIndex < 0) {
        this.currentGridPageIndex =
          Math.ceil(
            this.participantUserInfos.length / this.participantCountPerGridPage
          ) - 1
      }
    },
    nextPage() {
      if (
        this.participantUserInfos.length / this.participantCountPerGridPage >
        this.currentGridPageIndex + 1
      ) {
        this.currentGridPageIndex++
      } else {
        this.currentGridPageIndex = 0
      }
    },

    updateCountPerPage(count) {
      this.participantCountPerGridPage = count
    },

    setCurrentLayout(layout) {
      if (this.currentLayout === layout) {
        return
      }
      // 演讲者布局
      if (layout === 1) {
        // 演讲者布局，切换为小流，然后焦点用户切换为大流
        this.participantUserInfos.forEach((u) => {
          if (
            u.uid !== this.selfUserInfo.uid &&
            !u._isAudience &&
            !u._isVideoMuted
          ) {
            this.session.setParticipantVideoType(
              u.uid,
              u._isScreenSharing,
              VideoType.SMALL_STREAM
            )
          }
        })
      } else {
        //宫格布局， 当前页切换为大流，未显示的，取消订阅，由 currentPageParticipants 副作用触发
        this.currentGridPageIndex = 0
        conferenceManager.currentFocusUser = null
      }
      this.currentLayout = layout
      this.showChooseLayoutView = false
    },
    toggleParticipantListVideoView() {
      this.hideFocusLayoutParticipantListVideoView =
        !this.hideFocusLayoutParticipantListVideoView
    },

    hideConferenceSimpleInfoView(event) {
      if (event.target.id === 'info-icon') {
        return
      }
      this.showConferenceSimpleInfoView = false
    },

    hideChooseLayoutView(event) {
      if (event.target.id === 'grid-icon') {
        return
      }
      this.showChooseLayoutView = false
    },

    onUserInfosUpdate(userInfos = []) {
      for (let i = 0; i < this.participantUserInfos.length; i++) {
        let userInfo = userInfos.find(
          (u) => u.uid === this.participantUserInfos[i].uid
        )
        if (userInfo) {
          Object.assign(this.participantUserInfos[i], userInfo)
        }
      }
    },
  },

  computed: {
    duration() {
      if (this.currentTimestamp <= 0) {
        return '00:00'
      }
      let escapeMillis = this.currentTimestamp - this.startTimestamp
      return this.timestampFormat(escapeMillis)
    },

    speakingUserName() {
      let maxVolume = this.selfUserInfo._volume
      let speakingUserInfo = this.selfUserInfo
      this.participantUserInfos.forEach((u) => {
        if (u._volume > maxVolume) {
          speakingUserInfo = u
          maxVolume = u._volume
        }
      })
      if (!maxVolume) {
        return ''
      }

      return this.userName(speakingUserInfo)
    },

    currentPageParticipants() {
      if (this.currentLayout === 1) {
        return []
      }

      let focusUser = this.conferenceFocusUser
      // sort not in place，避免副作用
      let sortedParticipantUserInfos = [...this.participantUserInfos].sort(
        (o1, o2) => {
          if (focusUser) {
            if (
              o1.uid === focusUser.uid &&
              o1._isScreenSharing === focusUser._isScreenSharing
            ) {
              return -1
            }
            if (
              o2.uid === focusUser.uid &&
              o2._isScreenSharing === focusUser._isScreenSharing
            ) {
              return 1
            }
          }

          if (o1._isAudience && !o2._isAudience) {
            return 1
          } else if (!o1._isAudience && o2._isAudience) {
            return -1
          } else if (o1._isAudience && o2._isAudience) {
            return o1.uid.localeCompare(o2.uid)
          } else {
            if (o1._isScreenSharing && !o2._isScreenSharing) {
              return -1
            }
            if (!o1._isScreenSharing && o2._isScreenSharing) {
              return 1
            }
            if (!o1._isVideoMuted && o2._isVideoMuted) {
              return -1
            }
            if (o1._isVideoMuted && !o2._isVideoMuted) {
              return 1
            }
            return o1.uid.localeCompare(o2.uid)
          }
        }
      )

      let start = this.currentGridPageIndex * this.participantCountPerGridPage
      let end =
        start + this.participantCountPerGridPage >
        sortedParticipantUserInfos.length
          ? sortedParticipantUserInfos.length
          : start + this.participantCountPerGridPage
      return sortedParticipantUserInfos.slice(start, end)
    },

    gridPageCount() {
      return Math.ceil(
        this.participantUserInfos.length / this.participantCountPerGridPage
      )
    },

    conferenceFocusUser() {
      if (!conferenceManager || !conferenceManager.conferenceInfo) {
        return null
      }
      let focus = conferenceManager.conferenceInfo.focus
      if (!focus) {
        return null
      }
      let focusUser = this.participantUserInfos.find(
        (u) => u.uid === focus && u._isScreenSharing === true
      )
      if (!focusUser) {
        focusUser = this.participantUserInfos.find((u) => u.uid === focus)
      }
      return focusUser
    },
    conferenceLocalFocusUser() {
      return conferenceManager.localFocusUser
    },

    // 以用户手动选择的为准
    computedCurrentLayout() {
      if (this.currentLayout === -1 && this.conferenceFocusUser) {
        return 1
      }
      return this.currentLayout
    },

    // TODO 可以缓存到 conferenceManager 里面
    computedFocusVideoParticipant() {
      if (!this.session || this.currentLayout === 0) {
        console.log('computedSpeakingParticipant null')
        return null
      }
      let sp
      if (this.conferenceFocusUser && !this.conferenceFocusUser._isVideoMuted) {
        sp = this.conferenceFocusUser
      } else if (
        this.conferenceLocalFocusUser &&
        !this.conferenceLocalFocusUser._isVideoMuted
      ) {
        sp = this.conferenceLocalFocusUser
      } else if (this.speakingVideoParticipant) {
        sp = this.speakingVideoParticipant
      } else {
        sp = this.participantUserInfos.find(
          (u) =>
            !u._isAudience && !u._isVideoMuted && u._isScreenSharing === true
        )
        if (!sp) {
          sp = this.participantUserInfos.find(
            (u) => !u._isAudience && !u._isVideoMuted
          )
        }
      }

      if (sp) {
        conferenceManager.currentFocusUser = sp
      } else {
        if (this.session.screenSharing) {
          sp = this.selfUserInfo
        }
      }
      console.log('computedFocusVideoParticipant', sp)
      return sp
    },
  },

  watch: {
    participantUserInfos: {
      deep: true,
      handler(infos) {
        let audioOnly = true
        // console.log('participantUserInfos', this.session.screenSharing);
        if (this.session.screenSharing) {
          audioOnly = false
        } else {
          for (let i = 0; i < this.participantUserInfos.length; i++) {
            let u = this.participantUserInfos[i]
            if (!u._isAudience && !u._isVideoMuted) {
              audioOnly = false
              break
            }
          }
        }
        this.audioOnly = audioOnly

        // mute self audio
        let ref = this.$refs[this.selfUserInfo.uid + '-audio']
        if (ref && ref.length > 0) {
          this.$refs[this.selfUserInfo.uid + '-audio'][0].muted = true
        }
        if (this.audioOnly) {
          return
        }
        // 宫格布局
        if (this.currentLayout === 0) {
          let start =
            this.currentGridPageIndex * this.participantCountPerGridPage
          let end =
            start + this.participantCountPerGridPage >
            this.participantUserInfos.length
              ? this.participantUserInfos.length
              : start + this.participantCountPerGridPage
          let count = end - start
          let width = '100%'
          let height = '100%'
          if (count <= 1) {
            width = '100%'
            height = '100%'
          } else if (count <= 4) {
            width = '50%'
            height = '45%'
          } else if (count <= 9) {
            width = '33%'
            height = '33%'
          } else {
            // max 16
            width = '25%'
            height = '25%'
          }
          if (this.$refs.rootContainer) {
            this.$refs.rootContainer.style.setProperty(
              '--participant-video-item-width',
              width
            )
            this.$refs.rootContainer.style.setProperty(
              '--participant-video-item-height',
              height
            )
          }
        }
      },
    },
    currentPageParticipants: {
      deep: true,
      handler(newCurrentPageParticipants, oldCurrentPagePariticipants) {
        if (this.audioOnly) {
          return
        }
        if (this.currentLayout === 0) {
          let count = this.currentPageParticipants.length
          let width = '100%'
          let height = '100%'
          if (count <= 1) {
            width = '100%'
            height = '100%'
          } else if (count <= 4) {
            width = '50%'
            height = '45%'
          } else if (count <= 9) {
            width = '33%'
            height = '33%'
          } else {
            // max 16
            width = '25%'
            height = '25%'
          }
          if (this.$refs.rootContainer) {
            this.$refs.rootContainer.style.setProperty(
              '--participant-video-item-width',
              width
            )
            this.$refs.rootContainer.style.setProperty(
              '--participant-video-item-height',
              height
            )
          }
        }

        if (oldCurrentPagePariticipants) {
          oldCurrentPagePariticipants.forEach((u) => {
            if (
              u.uid === this.selfUserInfo.uid ||
              u._isAudience ||
              u._isVideoMuted
            ) {
              return
            }
            this.session.setParticipantVideoType(
              u.uid,
              u._isScreenSharing,
              VideoType.NONE
            )
          })
        }
        if (newCurrentPageParticipants) {
          newCurrentPageParticipants.forEach((u) => {
            if (
              u.uid === this.selfUserInfo.uid ||
              u._isAudience ||
              u._isVideoMuted
            ) {
              return
            }
            this.session.setParticipantVideoType(
              u.uid,
              u._isScreenSharing,
              VideoType.BIG_STREAM
            )
          })
        }
      },
    },

    computedFocusVideoParticipant(newFocusParticipant, oldFocusParticipant) {
      if (
        newFocusParticipant &&
        newFocusParticipant.uid !== this.selfUserInfo.uid
      ) {
        this.session.setParticipantVideoType(
          newFocusParticipant.uid,
          newFocusParticipant._isScreenSharing,
          VideoType.BIG_STREAM
        )
      }
      if (
        oldFocusParticipant &&
        oldFocusParticipant.uid !== this.selfUserInfo.uid
      ) {
        this.session.setParticipantVideoType(
          oldFocusParticipant.uid,
          oldFocusParticipant._isScreenSharing,
          VideoType.SMALL_STREAM
        )
      }
    },
  },

  directives: {
    vOnClickOutside,
  },

  created() {
    if (isElectron()) {
      document.title = '在线会议'
    }
    conferenceManager.setVueInstance(this)
    this.refreshUserInfoInternal = setInterval(() => {
      this.refreshUserInfos()
    }, 3 * 1000)

    this.$eventBus.$on('muteVideo', (mute) => {
      if (this.session.videoMuted !== mute) {
        let enable = this.session.videoMuted ? true : false
        this.enableVideo(enable)
      }
    })
    this.$eventBus.$on('muteAudio', (mute) => {
      if (this.session.audioMuted !== mute) {
        let enable = this.session.audioMuted ? true : false
        this.enableAudio(enable)
      }
    })
  },

  mounted() {
    this.setupSessionCallback()

    if (isElectron()) {
      //
      // this.$on('stop-screen-share', () => {
      //     this.session.stopScreenShare();
      //     this.$forceUpdate();
      // })
      window.addEventListener('mousemove', (event) => {
        if (!this.session || !this.session.screenSharing) {
          return
        }
        if (event.target.id === 'main-content-container') {
          currentWindow.setIgnoreMouseEvents(true, { forward: true })
        } else {
          currentWindow.setIgnoreMouseEvents(false)
        }
      })
      window.addEventListener('mouseleave', (event) => {
        currentWindow.setIgnoreMouseEvents(false)
      })
      this.$refs.rootContainer.style.setProperty(
        '--conference-container-margin-top',
        '30px'
      )
    } else {
      this.$refs.rootContainer.style.setProperty(
        '--conference-container-margin-top',
        '0px'
      )
    }
    wfc.eventEmitter.on(EventType.UserInfosUpdate, this.onUserInfosUpdate)
  },

  unmounted() {
    // reset
    this.$set(this.selfUserInfo, '_stream', null)
    this.participantUserInfos.forEach((m) => this.$set(m, '_stream', null))
    clearInterval(this.refreshUserInfoInternal)
    this.$eventBus.$off('muteVideo')
    this.$eventBus.$off('muteAudio')
    this.conferenceManager.destroy()
    wfc.eventEmitter.off(EventType.UserInfosUpdate, this.onUserInfosUpdate)
  },
}
</script>

<style lang="css" scoped>
.voip-container {
  background: #00000000 !important;
  position: relative;
  --conference-container-margin-top: 30px;
  --slider-width: 0px;
  --main-width: 100%;
}

a {
  color: gray;
}

i:hover {
  color: #1f64e4;
}

i.active {
  color: #3f64e4;
}

.main-slider-container {
  width: 100%;
  margin-top: var(--conference-container-margin-top);
  height: calc(100% - var(--conference-container-margin-top));
  display: flex;
  flex-direction: row;
}

.main-slider-container .main {
  width: calc(100% - var(--slider-width));
  height: 100%;
}

.main-slider-container .slider {
  width: var(--slider-width);
  height: 100%;
  overflow: auto;
  background: white;
}

.conference-main-content-container {
  width: 100%;
  height: calc(100% - 20px);
  position: relative;
  /*flex: 1;*/
  /*flex-direction: column;*/
  /*justify-content: space-between;*/
  /*align-items: center;*/
}

.content-container {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  align-content: center;
}

.main-slider-container .grid {
  flex-direction: row;
}

.main-slider-container .focus {
  --participant-video-item-width: 200px;
  --participant-video-item-height: 100px;
  flex-direction: column;
}

.content-container.video {
  background: black;
  object-fit: contain;
}

.focus-mode-participant-list-container {
  /*position: absolute;*/
  /*top: 0;*/
  /*right: 0;*/
  width: 200px;
  height: 100%;
  overflow: auto;
}

.content-container.audio {
  background: white;
  height: calc(100% - 50px);
  overflow: auto;
  padding: 10px 0 50px 0;
}

.participant-audio-item {
  display: flex;
  flex-direction: column;
  padding: 20px 40px;
  justify-content: center;
  align-items: center;
}

.hidden-video {
  height: 0;
}

.participant-audio-item .indicator {
  width: 18px;
  height: 18px;
  position: absolute;
  left: 50%;
  color: white;
  text-align: center;
  vertical-align: center;
  border-radius: 9px;
  bottom: 0;
  background: #d6d6d6;
  transform: translateX(-50%) translateY(25%);
}

.participant-audio-item p {
  padding-top: 8px;
}

.conference-main-content-container:hover footer {
  width: 100%;
  display: block;
  position: absolute;
  left: 0;
  bottom: 0;
  background: gray;
}

footer {
  /*height: 100px;*/
  display: none;
}

.duration-action-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.duration-action-container p {
  color: white;
  padding: 0 5px 0 0;
}

.action-container {
  /*width: 100%;*/
  display: flex;
  justify-content: center;
}

.action-container .action {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-size: 12px;
  color: white;
  padding: 0 25px 0 25px;
}

.avatar {
  width: 90px;
  height: 90px;
  border-radius: 45px;
}

.avatar.highlight {
  border: 2px solid #1fca6a;
}

.action-img {
  width: 40px;
  height: 40px;
}

.video.me {
  -webkit-transform: scaleX(-1);
  transform: scaleX(-1);
}

.rejoin-container {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #e0e0e0e0;
  text-align: center;
  justify-content: center;
  color: red;
}

.icon-ion-grid:after {
  padding-left: 5px;
  content: '\f13f';
}
</style>
